package com.whosly.strategy.scan.spring;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;

import java.util.HashSet;
import java.util.Set;

/**
 * 策略容器扫描器<br>
 * 扫描出所有策略容器接口进行加工处理
 *
 * @Author yueny09 <deep_blue_yang@126.com> @Date 2019-09-05 15:24
 */
public class StrategyContainerClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {
    public StrategyContainerClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        super(registry, false);
    }

    @Override
    public Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);

        if (beanDefinitions.isEmpty()) {
            return new HashSet<>();
        }

        processBeanDefinitions(beanDefinitions);

        return beanDefinitions;
    }

    /**
     * 处理beanDefinitions，替换掉策略容器接口的BeanClass类
     * @param beanDefinitions
     */
    private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
        GenericBeanDefinition definition;
        for (BeanDefinitionHolder holder : beanDefinitions) {
            // holder is IStrategyContainer 的子接口
            definition = (GenericBeanDefinition) holder.getBeanDefinition();

            String name = definition.getBeanClassName();
            definition.getPropertyValues().add("strategyContainerInterface", name);
            definition.setBeanClass(ContainerFactoryBean.class);
            definition.setLazyInit(true);

            definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_NAME);
        }
    }

    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return true;
    }

    /**
     * 获取 ClassLoader
     */
    private static ClassLoader getClassLoader() {
        return Thread.currentThread().getContextClassLoader();
    }
}
